# Parametric Curves and Parametric Surfaces

[Back to documentation index.](index.md)

<a id=Introduction></a>
## Introduction

This page describes parametric curves and surfaces and how to generate them using my
public-domain [HTML 3D Library](http://peteroupc.github.io/html3dutil).

**Download the latest version of the library at the [HTML 3D Library's Releases page](https://github.com/peteroupc/html3dutil/releases).**

<a id=Contents></a>
## Contents

- [Introduction](#Introduction)
- [Contents](#Contents)
- [What Is a Parametric Surface?](#What_Is_a_Parametric_Surface)
    - [Why two variables?](#Why_two_variables)
- [Parametric Surfaces in the HTML 3D Library](#Parametric_Surfaces_in_the_HTML_3D_Library)
- [Chaining Surface Functions](#Chaining_Surface_Functions)
- [Parametric Curves](#Parametric_Curves)
    - [Generating Parametric Curves](#Generating_Parametric_Curves)
- [Curve and Surface Evaluators in the HTML 3D Library](#Curve_and_Surface_Evaluators_in_the_HTML_3D_Library)
- [Demos](#Demos)
    - [Creating Your Own Curves and Surfaces](#Creating_Your_Own_Curves_and_Surfaces)
- [Other Pages](#Other_Pages)

<a id=What_Is_a_Parametric_Surface></a>
## What Is a Parametric Surface?

A _parametric surface_ is a surface generated by evaluating the results of a _vector function_. This vector function
takes two numbers, U and V, and returns a 3D point, X, Y, and Z. Each (U, V) point corresponds to an (X, Y, Z)
point that lies on the surface.

A _vector function_ in 3D is a combination of three functions, one for each dimension:

* **F**(u, v) = [ _x_(u, v), _y_(u, v), _z_(u, v) ];

The _x_ function returns an X coordinate given u and v, and likewise for _y_ and _z_.
Since the _z_ function returns a Z coordinate, the surface will be in 2D if _z_ always returns
the same value.

For example, if we have a parametric surface defined by the following functions:

* _x_(u, v) = u \* v
* _y_(u, v) = -u
* _z_(u, v) = u \* sqrt(v)

and we evaluate the UV point (2, 4), then we have:

* **F**(2, 4) = [ 2 \* 4, -2, 2 \* sqrt(4) ];
* **F**(2, 4) = [ 8, -2, 4 ];

So (8, -2, 4) is one point that lies on this parametric surface, and any other point on the
surface can be found by evaluating different UV points. By the way, the surface looks like this:

![The parametric surface.](surfaces1.png)

<a id=Why_two_variables></a>
### Why two variables?

The surface functions take two variables, _u_, and _v_, because a parametric
surface can be a seen as a "warped" version of a rectangular grid. The vector
function "warps" this grid into a three-dimensional surface.

<a id=Parametric_Surfaces_in_the_HTML_3D_Library></a>
## Parametric Surfaces in the HTML 3D Library

The HTML 3D Library supports parametric surfaces using a class named
[`SurfaceBuilder`](http://peteroupc.github.io/html3dutil/H3DU.SurfaceBuilder.html). It helps
generate vertex coordinates and other attributes using a parametric surface
function. The following helper function, `makeMesh`, generates a parametric surface mesh.
A function similar to the `makeMesh`
function presented here is included in the demos that come with the HTML 3D Library.

The comments explain how `makeMesh` works in detail.

    function makeMesh(func,resolutionU, resolutionV){
       "use strict";
       if(typeof resolutionV === "undefined" || resolutionV === null)resolutionV = resolutionU;
       if(typeof resolutionU === "undefined" || resolutionU === null)resolutionU = 50;
       if(typeof resolutionV === "undefined" || resolutionV === null)resolutionV = 50;
          // define a color gradient evaluator for
          // demonstration purposes. Instead of X, Y, and Z,
          // generate a Red/Green/Blue color based on
          // the same parameters U and V as the surface
          // function for 3D points.
       var colorGradient = {
         "evaluate":function(u, v) {
           return [1 - u, v, u];
         }
       };
       return new H3DU.SurfaceBuilder()
          .positionNormal(func)
          .attribute(colorGradient, H3DU.Semantic.COLOR)
         // Evaluate the surface and generate a triangle
         // mesh, using resolution+1 different U coordinates,
         // and resolution+1 different V coordinates.
         // Instead of H3DU.Mesh.TRIANGLES, we could use
         // H3DU.Mesh.LINES to create a wireframe mesh,
         // or H3DU.Mesh.POINTS to create a point mesh.
          .evalSurface(H3DU.Mesh.TRIANGLES, resolutionU, resolutionV)
          .toMeshBuffer();
    }

In the HTML 3D Library, surface evaluator objects define a method, `evaluate`,
which returns a 3D point given a U parameter and a V parameter. (By default, U and
V each range from 0 through 1.)

The following code is a very simple surface evaluator object.

    var evaluator = {
      "evaluate":function(u, v){
        // Take the U parameter as the X coordinate,
        // the V parameter as the Y coordinate, and 0 as
        // the Z coordinate.
        return [u, v, 0];
      }
    }

That evaluator simply generates a square at the top-right quadrant:

![The parametric surface.](surfaces2.png)

And the following evaluator generates a circle:

    var evaluator = {
      "evaluate":function(u, v){
         // Return circle coordinates.
         return [u*Math.cos(v),u*Math.sin(v),0];
      },
      // Declare the usual range of the coordinates
      "endPoints":function(){ return [0,1,0,Math.PI*2]; }
    }

![The parametric surface.](surfaces3.png)

Now here's the interesting part: This evaluator returns not a circle,
but a _cone_, whose length runs along the negative Z axis:

    var evaluator = {
      "evaluate":function(u, v){
         // Return cone coordinates, using the u
         // parameter as the Z axis.
         return [u*Math.cos(v),u*Math.sin(v),-u];
      },
      // Declare the usual range of the coordinates
      "endPoints":function(){ return [0,1,0,Math.PI*2]; }
    }

The following shape was rotated to show the Z axis; the rotation isn't perfect.

![The parametric surface.](surfaces4.png)

Note that all three examples above use a value named `evaluator`. To generate
a mesh with an evaluator and add it to the 3D scene, you then need to do:

    // Assumes that a Scene3D object named _scene_ was previously defined.
    // Create a 3D shape using the makeMesh method given earlier on this page
    var shape = new H3DU.Shape(makeMesh(evaluator));
    // Add the shape to the 3D scene
    scene.addShape(shape);

The generated 3D mesh from a parametric surface is just like any
other mesh, and the same functions and methods you use for other meshes
can be used on this mesh as well. For more information, see the
[overview page](http://www.codeproject.com/Tips/896839/Public-Domain-HTML-ThreeD-Library)
and the API references for the [`H3DU.Mesh`](http://peteroupc.github.io/html3dutil/H3DU.Mesh.html) and
[`Shape`](http://peteroupc.github.io/html3dutil/H3DU.Shape.html) classes.

<a id=Chaining_Surface_Functions></a>
## Chaining Surface Functions

The technique of using surface evaluator objects is very flexible. In fact, you can chain evaluators,
using the output of one evaluator as the input of another evaluator. This can be used
to transform the surface's points to new positions.

As an example, we'll define a new evaluator that shifts the position
of a parametric surface. It takes an existing surface evaluator and the X, Y, and
Z of how many units to shift the surface. Note that this class includes its
own `evaluate` method, allowing itself to be passed to the `H3DU.SurfaceBuilder` class's method
or the makeMesh method above.

    function SurfaceShifter(evaluator, x, y, z) {
     // Shift the surface by X units.
     this.x = x;
     // Shift the surface by Y units.
     this.y = y;
     // Shift the surface by Z units.
     this.z = z;
     this.evaluator = evaluator;
     // Define the surface shifter function
     this.evaluate = function(u, v){
      // Get the coordinates from the source evaluator
      var retval = this.evaluator.evaluate(u, v);
      // Shift the coordinates
      retval[0]+=this.x;
      retval[1]+=this.y;
      retval[2]+=this.z;
      // And return the new coordinates.
      return retval;
     }
     this.endPoints=function(){
      return this.evaluator.endPoints()
     }
    }

And here's an example of its use. We'll take the circle surface given above,
and create a SurfaceShifter object that shifts the circle by 3 units horizontally
and vertically (by default, the circle will be centered at the origin (0, 0, 0)).

    // This is the circle surface from before
    var evaluator = {
      "evaluate":function(u, v){
         // Extend the range of v
         v*=Math.PI*2;
         // Return circle coordinates.
         return [u*Math.cos(v),u*Math.sin(v),0];
      },
      "endPoints":function() { return [0,Math.PI*2] }
    }
    // Create a shifter that results in the circle being moved 3 units
    // up and 3 units to the right
    evaluator = new SurfaceShifter(evaluator, 3, 3, 0);

<a id=Parametric_Curves></a>
## Parametric Curves

The HTML 3D library also includes support for generating parametric curves.
A _parametric curve_ is a curve generated by a vector function, like a parametric
surface, except now, the function only uses a single variable, as shown below:

* **C**(u) = [ _x_(u), _y_(u), _z_(u) ];

As before, the _x_, _y_, and _z_ functions return the corresponding
coordinates of the curve.
And each (U) point corresponds to an (X, Y, Z) point that lies on the curve.

The curve function takes a single _u_ variable because a parametric
curve can be a seen as a "warped" version of a line.

One simple example of a parametric curve is a circle. In fact, the same source
code for the circle surface given above can also serve as the parametric curve
function, since it only uses the variable _u_, not _v_.

Note that any surface evaluator that only uses _u_ can easily serve as a
parametric curve evaluator, as can any surface in which the _v_ parameter is
kept to the same value, such as 0, 1, or any other constant number.

<a id=Generating_Parametric_Curves></a>
### Generating Parametric Curves

The HTML 3D Library's `H3DU.CurveBuilder` class generates vertices for
a parametric curve.

Use code like the following to generate a mesh describing a parametric
curve. It assumes that `evaluator` is a parametric curve object, just like
the circle example above.

      // Create a curve evaluator
      var ev=new H3DU.CurveBuilder()
      .position(evaluator)
       // Evaluate the curve, using 99 lines (100 points). Alternatively,
       // H3DU.Mesh.POINTS can be used.
      .evalCurve(H3DU.Mesh.LINES,100);
      // Create a mesh describing the curve
      var mesh=ev.toMeshBuffer()

<a id=Curve_and_Surface_Evaluators_in_the_HTML_3D_Library></a>
## Curve and Surface Evaluators in the HTML 3D Library

The HTML 3D Library distribution includes the following evaluators of
curves and surfaces. All the classes named below include an `evaluate`
method that returns 3D points lying on the curve or surface.

General-purpose curves include:

* **B-spline curves.** These curves consist of control points (which control
the shape of the curve but don't necessarily lie on the curve), and a
_knot vector_, which controls the behavior of the control points. B-spline
curves include **NURBS** curves (nonuniform and rational B-spline curves,
with weights and non-uniform knots), making them a powerful way of setting the
behavior of a curve. B-Spline curves are created using the
 <a href="H3DU.BSplineCurve.md">H3DU.BSplineCurve</a> class.
* **B&eacute;zier curves.** These are curves in which the first and last
control point are the curve's end points. B&eacute;zier curves are a subset of B-spline
curves and are created using the <a href="H3DU.BSplineCurve.md#H3DU.BSplineCurve.fromBezierCurve">H3DU.BSplineCurve.fromBezierCurve</a>
method.
* **Piecewise curves** These are curves made up of one or more other curves.
Piecewisec curves are created using the <a href="H3DU.PiecewiseCurve.md">H3DU.PiecewiseCurve</a> class.

Special curves include the following. All of these classes are supplemental
extras.

* **<a href="H3DU.Epitrochoid.md">H3DU.Epitrochoid</a>** - A
curve drawn by a circle rolling along the outside of another circle.
* ** <a href="H3DU.Hypotrochoid.md">H3DU.Hypotrochoid</a>** - A
curve drawn by a circle rolling along the inside of another circle.
* ** <a href="H3DU.Trochoid.md">H3DU.Trochoid</a>** - A
curve drawn by a circle rolling along a straight line.

General-purpose surfaces include:

* **B&eacute;zier surfaces.** 3D surfaces where each grid line is a B&eacute;zier
curve. B&eacute;zier surfaces are created using the <a href="H3DU.BSplineSurface.md#H3DU.BSplineSurface.fromBezierSurface">H3DU.BSplineSurface.fromBezierSurface</a> method.
* **B-Spline surfaces.** 3D surfaces where each grid line is a B-Spline or NURBS
curve. B-Spline surfaces are created using the <a href="H3DU.BSplineSurface.md">H3DU.BSplineSurface</a> class.

Special surfaces include:

* **Tubes.** 3D surfaces in the form of a "thickened" 3D curve.
Tubes are created using the <a href="H3DU.CurveTube.md">H3DU.CurveTube</a> class,
a supplemental extra in the HTML 3D library.
* **Surfaces of revolution.** Surfaces generated by rotating a 2D curve.
Surfaces of revolution are created using the <a href="H3DU.SurfaceOfRevolution.md">H3DU.SurfaceOfRevolution</a> class,
a supplemental extra in the HTML 3D library.

<a id=Demos></a>
## Demos

* [surfaces.html](https://peteroupc.github.io/html3dutil/demos/surfaces.html) - Demonstrates parametric surfaces.

This demo contains several examples of parametric surfaces. The source code defines several classes that create evaluators of parametric surfaces:

* `new Superellipsoid(xRadius, yRadius, zRadius, n, m)`<br>
   Creates a "[superellipsoid](http://en.wikipedia.org/wiki/Superellipsoid)" shape, with a radius `xRadius` along the X axis,
   `yRadius` along the Y axis, and `zRadius` along the Z axis. The parameters `m` and `n` may be omitted; the default for each is 1, which creates a normal ellipsoid.
* `new Supertoroid(xRadius, yRadius, zRadius, innerRadius, n, m)`<br>
   Creates a "[supertoroid](http://en.wikipedia.org/wiki/Supertoroid)" shape (with a hole in the middle), with a radius `xRadius` along the X axis, `yRadius` along the Y axis, and `zRadius` along the Z axis. The inner radius will be `innerRadius`. The parameters `m` and `n` may be omitted; the default for each is 1, which creates a normal torus or toroid.
* `new KleinBottle()`<br>Creates a Klein bottle.
* `new MoebiusStrip()`<br>Creates a M&ouml;bius strip.

These are only some of the many possible kinds of parametric surfaces.

* [demos/bsplinecircles.html](https://peteroupc.github.io/html3dutil/demos/bsplinecircles.html) - Demonstrates how circles and ellipses can be generated using the `BSplineCurve` class.

<a id=Creating_Your_Own_Curves_and_Surfaces></a>
### Creating Your Own Curves and Surfaces

Two other demos include a formula editor allowing you to experiment with
parametric curves and surfaces, and to export them to source code appropriate
for use in the Public Domain HTML 3D Library.

* [curvesexpr.html](https://peteroupc.github.io/html3dutil/demos/curvesexpr.html) - Demonstrates parametric
curves, with a custom formula editor.
* [surfacesexpr.html](https://peteroupc.github.io/html3dutil/demos/surfacesexpr.html) - Demonstrates parametric
surfaces, with a custom formula editor.

<a id=Other_Pages></a>
## Other Pages

The following pages of mine on CodeProject also discuss this library:

* [_Public-Domain HTML 3D Library_](http://www.codeproject.com/Tips/896839/Public-Domain-HTML-ThreeD-Library)
* [_Creating shapes using the Public Domain HTML 3D Library_](http://www.codeproject.com/Tips/987914/Creating-shapes-using-the-Public-Domain-HTML-D-Lib)
* [_The "Camera" and the Projection and View Transforms_](http://www.codeproject.com/Tips/989978/The-Camera-and-the-Projection-and-View-Transforms)
* [_Graphics Filters for the HTML 3D Canvas_](http://www.codeproject.com/Articles/993433/Graphics-Filters-for-the-HTML-D-Canvas)

[Back to documentation index.](index.md)
